package work.month06.day05;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

/**
 * @date 2020/06/04
 * @author 王光浩
 * @introduction 创建一个集合类
 */
public class Container implements Collection<Object> {

//==================  静态字段 ====================================

	private static final int DEFAULT_INITIAL_CAPACITY = 10; // 默认初始容量的常量
	private static final float DEFAULT_LOADFACTOR = 1;// 默认装载因子常量
	private static final int MAXIMUM_CAPACITY = 1 << 30; // 最大容量
	private static final Object UNUSE = new Object(); // 用于标志该位置尚未被使用

// ==================  实例字段 ====================================

	private Object[] elements; // 保存集合中的元素
	private float loadFactor; // 装载因子值
	private int size; // 元素的个数
	private final StringBuilder str = new StringBuilder(); // 用与在 toString 方法中，进行结果的拼接（重复利用）

// ==================  构造方法 =====================================

	/**
	 * 默认大小，默认装载因子集合对象的构造方法
	 */
	public Container() {
		this(Container.DEFAULT_INITIAL_CAPACITY, Container.DEFAULT_LOADFACTOR);
	}

	/**
	 * 创建一个指定大小，默认装载因子集合对象
	 * @param initialCapacity
	 */
	public Container(int initialCapacity) {
		this(initialCapacity, Container.DEFAULT_LOADFACTOR);
	}

	/**
	 * 创建一个指定装载因子，默认大小集合对象
	 * @param loadFactor
	 */
	public Container(float loadFactor) {
		this(Container.DEFAULT_INITIAL_CAPACITY, loadFactor);
	}

	/**
	 * 创建一个指定大小，指定装载因子集合对象的构造方法
	 * @param initialCapacity
	 * @param loadFactor
	 */
	public Container(int initialCapacity, float loadFactor) {
		if (initialCapacity < 0 || initialCapacity > Container.MAXIMUM_CAPACITY)
			throw new RuntimeException("容量必须是 0 ~" + Container.MAXIMUM_CAPACITY + "之间");
		if (loadFactor <= 0 || loadFactor > 1)
			throw new RuntimeException("加载因子必须是  (0 ~ 1]之间");
		this.elements = new Object[initialCapacity];
		this.loadFactor = loadFactor;
		this.size = 0;
		Arrays.fill(this.elements, Container.UNUSE);
	}

// ==================  实例方法 =====================================

	/**
	 * 向集合中添加一个元素
	 * @param o
	 * @return
	 */
	@Override
	public boolean add(Object o) {
		if (size >= (int) (this.elements.length * this.loadFactor))
			this.grow();
		this.elements[size++] = o;
		return true;
	}

	/**
	 * 将 集合 c 中的所有元素添加到 该集合对象中
	 * @return 如果集合对象个数发生改变则返回 true
	 */
	@Override
	public boolean addAll(Collection<? extends Object> c) {
		if (c == null)
			return false;
		if (c.getClass() != Container.class)
			throw new RuntimeException("传入的参数需要是 Container 类型的");
		Container co = (Container) c;
		for (int i = 0; i < co.size(); i++) {
			add(co.elements[i]);
		}
		return true;
	}

	/**
	 * 判断 指定的对象 在集合中是否存在，存在 返回 true，否则返回 false
	 * @param o
	 * @return
	 */
	@Override
	public boolean contains(Object o) {
		return indexOf(o) != -1;
	}

	/**
	 * 判断 c 中的所有元素是否在 该集合对象中是否存在
	 * @return 如果指定集合 与 该集合对象存在 交集，则返回 ture,否则返回 false
	 */
	@Override
	public boolean containsAll(Collection<?> c) {
		if (c == null)
			return false;
		if (c.getClass() != Container.class)
			throw new RuntimeException("传入的参数需要是 Container 类型的");
		Container co = (Container) c;
		for (int i = 0; i < co.size(); i++) {
			if (indexOf(co.elements[i]) == -1)
				return false;
		}
		return true;
	}

	/**
	 * 从集合中删除所有指定的对象
	 * @param o
	 * @return	返回集合中存在该对象的个数，如果没有的话，则返回 0
	 */
	@Override
	public boolean remove(Object o) {
		int i = indexOf(o);
		if (i == -1)
			return false;
		for (i += 1; i < size; i++)
			elements[i - 1] = elements[i];
		elements[size - 1] = Container.UNUSE;
		size--;
		return true;
	}

	/**
	 * 删除本集合对象中 与指定集合中存在交集部分的所有元素
	 * @return 如果成功删除了元素，则返回 true，否则返回 false
	 */
	@Override
	public boolean removeAll(Collection<?> c) {
		boolean help = false;
		if (c == null)
			return help;
		if (c.getClass() != Container.class)
			throw new RuntimeException("传入的参数需要是 Container 类型的");
		Container co = (Container) c;
		//进行删除元素
		for (int i = 0; i < co.size; i++) 
			help = remove(co.elements[i]);
		return help;
	}

	/**
	 * 以数组的形式返回集合中存储的对象
	 * @return
	 */
	@Override
	public Object[] toArray() {
		return Arrays.copyOf(elements, size);
	}

	/**
	 * 寻找指定元素在容器中的索引
	 * @param o target object
	 * @return 找到时返回索引，否则返回 -1
	 */
	public int indexOf(Object o) {
		for (int i = 0; i < size; i++) {
			Object e = elements[i];
			if (e == o || (e != null && e.equals(o)))
				return i;
		}
		return -1;
	}

	/**
	 * 保留该集合 和 指定集中元素的交集
	 * @return 如果该集合中的元素个数发生改变则返回 true，否则返回 false
	 */
	@Override
	public boolean retainAll(Collection<?> c) {
		boolean help = false;
		if (c == null)
			return help;
		if (c.getClass() != Container.class)
			throw new RuntimeException("传入的参数需要是 Container 类型的");
		Container co = (Container) c;
		for (int i = 0; i < size; i++) {
			//在 c 中不存在该元素
			if (co.indexOf(this.elements[i]) == -1) { 
				help = true;
				remove(elements[i]);
			}
		}
		return help;
	}
	
	/**
	 * 判断是否为空
	 * @return
	 */
	@Override
	public boolean isEmpty() {
		return this.size == 0;
	}

	/**
	 * 返回集合中元素的格式
	 * @return
	 */
	public int size() {
		return this.size;
	}

	/**
	 * 将集合清空
	 */
	@Override
	public void clear() {
		this.size = 0;
		this.fillUnuse();
	}

	/**
	 * 自定义 toString 方法
	 */
	@Override
	public String toString() {
		str.append("[");
		for (int i = 0; i < this.size - 1; i++) {
			str.append(this.elements[i] + ",");
		}
		if (this.size > 0)
			str.append(this.elements[size - 1]);
		str.append(']');
		String s = str.toString();
		str.setLength(0); // 类似于将 StringBuilder 清空
		return s;
	}

	/**
	 * 进行扩容
	 */
	private void grow() {
		final Object[] temp = this.elements;
		// 确定新数组的容量
		int newLength = (temp.length * 3) / 2 + 1;
		// 判断扩容后是否溢出
		if (newLength <= 0 || newLength > Container.MAXIMUM_CAPACITY)
			newLength = Container.MAXIMUM_CAPACITY;
		this.elements = new Object[newLength];
		this.fillUnuse();
		// 将原数组内容 copy 到 新数组中
		System.arraycopy(temp, 0, elements, 0, size);
	}

	/**
	 * 将数组中的所有位置标记为 未使用
	 */
	private void fillUnuse() {
		Arrays.fill(this.elements, Container.UNUSE);
	}
	
	@Override
	public Iterator<Object> iterator() {
		// TODO Auto-generated method stub
		return null;
	}

	@Override
	public <T> T[] toArray(T[] a) {
		// TODO Auto-generated method stub
		return null;
	}
}
